<nodeExecutor>

A node is an Object array containing other arrays whose sizes depend on eachother.

Using a node as the definition of another node is hard. This example is hard to make consistent in all parts:
simpleNeuralNodeDef = Object[]{
	int[]{ theUniqueIntOfSimpleNeuralNodeDef }
	Object arrayTypes[] //Example[x]: objectRepresentingBayesNodeType
	Object sizeOps[] //Example[x]: objectRepresentingThePowerFunction
	Object sizeLvalues[] //Example[x]: objectWithArraySize2
	Object sizeRvalues[] //Example[x]: objectRepresentingSizeBetween1And6
}
Therefore I will try to define some node executor functions (that may evolve) because
they depend on how a node is defined, and use that to choose how to define nodes.

public interface NodeExecutor{ //TODO choose better name for this interface
	public void run(Object nodeDef[], Object node[]);
}

<question>
	Should the node definition be a parameter of the function that executes the node?
	The definition may only be needed when creating the node executor function.
</question>

<question>
	A node is an Object array, but a node executor usually does not use all arrays in that array,
	so should a node executor function's parameter be a smaller Object array which contains
	only the arrays that it would use?
	<question>
		Should it take 3 parameters like this:
		public interface IntsFlosObsExecutor{ //TODO choose better name for this interface
			public void run(int intArrays[][], double floArrays[][], Object obArrays[][]);
		}
		This does not simplify it because it still has to have the correct sizes of the 3 parameter arrays.
	</question>
</question>

public interface NodeExecutor{ //TODO choose better name for this interface
	public void run(Object node[]);
}

public interface Obfunc{
	public Object run(Object node); //cast node to Object[]. Ignore the return value.
}

Obfunc bayesNodeWeightSumExecutor = new Obfunc(){
	public Object run(Object node){
		Object n[] = (Object[]) node;
		Object bayesChilds[] = (Object[]) n[4];
		double bayesWeights[] = (double[]) n[5];
		double bayesWeightSums[] = (double[]) n[6];
		for(int childIndex=0; childIndex<bayesChilds.length; childIndex++){
			for(int weightIndex=0; weightIndex<bayesWeights.length; bayesWeights++){
				int childBit = ((1 << childIndex) & weightIndex) >> childIndex; //optimized for size 2 [false,true]
				int weightSumsIndex = childBit*bayesChilds.length + childIndex;
				bayesWeightSums[weightSumsIndex] += bayesWeights[weightIndex];
			}
		}
		//Then there are a few more Obfuncs to use the bayesWeightSums and calculate things based on new child chances etc.
		return null;
	}
}
How would I define that in a way that allows variations of it to be evolved?


Define things as small parts involving multiply and power of array sizes, and a few ways to modify int arrays during iteration.

[x multiply y] is somehow connected to [x power y].
Abbreviate it: x*y is somehow connected to x^y.

Add more related things:
x*y=m
x^y=p


For each positive x and y, m=x*y and p=x^y, and these are ways of iterating over combinations of x, y, m, and p:
1 of x.
all of x.
1 of y.
all of y.
1 of m.
all of m.
1 of p --> all of y (each in range 0 to x-1).

How to represent y*(x^y)? Only 1 of the 2 ys has to exist as part of an array size. The other can be for iteration size only.
1 of p (unique) --> 1 of m (duplicate).

==========================

array(???) is a sequence of data that must all existin memory simultaneously.

iterate(???) is a sequence of parts of an array, or combinations of parts of arrays, that overwrites its previous state with its next state as it iterates over all combinations of those array(s).

foreach(x) is x.size iterations, data size 1.

allconcat(x) is 1 iteration, data size x.size.

*(x,y) is m, and x.size * y.size == m.size, and foreach(m) is foreach(x)*y.size + foreach(y).

^(x,y) is p, and x.size power.

==========================

How to iterate size y*(x^y) over data size x^y and/or data size x*y.

???
/( ^(x,y), x ) means the subset of the x^y iterations where x has a certain value.

/( ^(x,y), y ) may mean the same as THERE EXISTS a y equal to a specific value (which is between 0 and x-1)
instead of FOR ALL y.

It can be iteration size and data size x^y and still single out a specific y if you want.
Maybe the 4th y during iterating over ^(x,y) should be y[3]. Or should that mean the 4th x?
3^5 means 3*3*3*3*3, which is the multiply of 5 loops each looping 0 to 2. Should y[3] mean the 4th loop?

==========================

* is multiply.

^ is power.

*(foreach(x),foreach(y)) is x.size * y.size iterations and data size.

*(foreach(x),allconcat(y)) is x.size iterations, data size y.size.

*(allconcat(x),allconcat(y)) is 1 iteration and x.size + y.size data size, but does it make sense for * to concat?

^(foreach(x),foreach(y)) does not make sense. For example, if x.size==3 and y.size==5 then a loop in a loop would total 15 iterations, but ^(3,5) has data size 243.

???
^(foreach(x),allconcat(y)) is x.size ^ y.size iterations (x.size quantity of nested loops) and y.size data size.

???
^(allconcat(x),foreach(y)) is ? iterations and ? data size.

^(allconcat(x),allconcat(y)) is 1 iteration and x.size ^ y.size data size.

==========================

Maybe a better solution is to try to combine * with allconcat and combine ^ with foreach and allow recursion in those 2 things.

cat //is an abbrev of allconcat*
each //is an abbrev of foreach^

These 2 definitions are confusing because they sometimes mean plus/concat, multiply, and/or power.

LoopX power loopY, in some interpretations, means Y quantity of loopXs, and that sounds a lot like Y multiply loopX.

==========================

//List of ideas about things with integer size:

space //exists all at the same time. Example: an array or the concat of some arrays.
time  //A sequence of changes, like iterating a loop. Example: iterate over each thing in an array.

space(b) = 2
space(c) = 3
space(d) = 4
space(e) = b*c
space(f) = d^e //d^(b*c)
//could view d^(b*c) as (d^b)^c

If iterating a single int over d^(b*c) or (d^b)^c, the same 3 ints would result, each e.size quantity of times.
Those 3 ints are indexs in d, b, and c. 0 to d-1. 0 to b-1. 0 to c-1. 1 combination of those for each int from 0 to f-1.
Those ints can be optimized as Java code and not exist as ints, but I should build it the slow and simple way first.

Ints from 0 to f-1 could also be viewed as b*c quantity of ints each from 0 to d-1.
Similarly, if f is viewed as (d^b)^c, that int from 0 to f-1 can be viewed as c quantity of ints from 0 to d^b-1.

I'm starting to think that FACTORIAL is a good function for some nodes, to use with MULTIPLY and POWER,
but it is much more complex.
Example: factorial(5) is 5*4*3*2*1 = 120.
An array size 120 is [Which of 5 is first?]*24 + [Which of the other 4 is second?]*6 + ...
For each of the 120 possible int values, its hard to calculate which order of [0,3,4,1,2] it means,
but there may be an efficient way to do it.

Triangle array may also be a good function. Should it include the diagonal of the triangle, where a node is combined with itself?
factorial(5) is 5*4*3*2*1, and tri(5) with diagonal is 5+4+3+2+1,
so those 2 could be combined in a loop the same way as multiply and power are combined,
but the triangle array is not useful combined with factorial because, for lower indexs,
the smaller parts of the diagonal do not align with themself when other things vary.
For example, the second biggest can be [0,1,2,3] or [0,1,2,4]  or [0,1,3,4] etc.

Factorial is useful to use with multiply and power because it can try calculations in all possible orders
and verify all orders create the same numbers (except for roundoff).

Example use of factorial with a bayes node:
5 childs sorted by something. factorial(5) is 120 numbers. Increase 1 of those 120 numbers.
Remember which orders of the childs happen how often.

Factorial could be used in a new type of node that watches sequences of nodes. Example:
Network of 1000 facnodes. Each facnode has 4 childs therefore 24 numbers.
Give all 1000 nodes random childs from those 1000.
Input many long sequences of nodes from those 1000 and set the 24 numbers in each with those statistics.
Usually the childs of a node are not input 1 after the other. Other nodes are input between them,
but because they are not childs of node x, node x ignores them in node x's statistics.
Now the network can predict which nodes will be input before and after other nodes, allowing a few random nodes to appear in the sequence that was predicted and still call it a good prediction.
Using the whole network to predict new sequences, more accurate nodes can be added that predict sequences more accurately in shorter times.

Learning sequences (instead of unordered sets of numbers always paired with the same nodes) can also be done with power and multiply.
For example, each bayes node could represent 1 chance. If false, word y will come some time after word x and before word z. If true, word z will come some time after word x and before word y.

***********This factorial stuff is complex and should be added after POWER and MULTIPLY are added and the first version of Audivolv is working with mouse and speakers.***********

All code should execute inside a network.
For example, a sound-generating code that plays a sound that depends on mouse position may be size-1 network that has a flo array contaning mouse position and speaker values. It reads the mouse positions from that array, and maybe reads the previous speaker values from that array, and writes new speaker values to that array. For efficiency, slower network operations could be done much less often than executing that simple code in the first node. For example, every 100 executions, recalculate some slower vars, and every 3000 executions, execute a small network of nodes, and every 100000 executions, do a small amount of some long-term AI calculations. That can be made efficient by only checking for the bigger execution intervals when the next smaller is already true, maybe by the size-1 network pointing at bigger networks and only executing them every 100 executions of the size-1 network.



=====================Starting from what I wrote above=======================

[QUOTE FROM ABOVE]
//List of ideas about things with integer size:

space //exists all at the same time. Example: an array or the concat of some arrays.
time  //A sequence of changes, like iterating a loop. Example: iterate over each thing in an array.

space(b) = 2
space(c) = 3
space(d) = 4
space(e) = b*c
space(f) = d^e //d^(b*c)
//could view d^(b*c) as (d^b)^c

If iterating a single int over d^(b*c) or (d^b)^c, the same 3 ints would result, each e.size quantity of times.
Those 3 ints are indexs in d, b, and c. 0 to d-1. 0 to b-1. 0 to c-1. 1 combination of those for each int from 0 to f-1.
Those ints can be optimized as Java code and not exist as ints, but I should build it the slow and simple way first.

Ints from 0 to f-1 could also be viewed as b*c quantity of ints each from 0 to d-1.
Similarly, if f is viewed as (d^b)^c, that int from 0 to f-1 can be viewed as c quantity of ints from 0 to d^b-1.
[END QUOTE FROM ABOVE]

f has data size f.size and iterationIndex size 1 and iteration size f.size.
//f = d^e = d^(b*c)

d^e has data size f.size and iterationIndex size 2 and iteration size e.size*f.size.
If iterating over d*e and f, each iteration has an index for d and an index for e.

d^e can be iterated a similar way by replacing 1 of the loops with a concat, but that will be useful less often.
Each iteration, a func is called with e.size parameters, selected from data with size d.size*e.size.
Iteration size f.size.
IterationIndex size 1 (in d*e) instead of iterationIndex size 2 (in d and in e).
This is the same as the other way of using d*e with d^e except that e.size iterations are grouped together to increase the iterationIndex size and decrease the iteration size. The total quantity of operations is equal.

"IterationIndexs: 0 to x.size-1" is abbrev below as "IterIndexs: x". Similar for IterSize.

Iteration option for b, a single array. This option is inherited by all other iterations and can be used simultaneously with other indexs.
Iteration size: b.size.
IterIndexs: b.

First iteration option for d^e:
IterSizes: e*(d^e).
IterIndexs: e, d, d^e, e*(d^e).

Second iteration option for d^e, inherited from linear iteration of single array:
IterSizes: d^e.
IterIndexs: d^e.

Iteration option for g*h:
IterSizes: g*h.
IterIndexs: g, h, g*h.
Faster if use only IterIndexs g*h, inherited from linear iteration of single array.

Try to combine "Second iteration option for d^e" and "Iteration option for g*h" to increase iteration size but not increase data size.

i = g*h
g = e
d = d
h = d^e
i = e*(d^e)

Add iterSize e.
Add iterSize d^e.
Add iterSize e*(d^e).

Where would iterSize d come from?
Should all vars always be included as single array in iterSize? h = d^e so d and e must be included.
d is included but there are too many ds. There are e quantity of ds because e is the exponent.
Each d has a value from 0 to e-1.

The problem may be that the quantity of iterIndexs of d^e is not constant. It depends on e.
The iterIndexs of d^e are: d^e, e[0], e[1], e[2], e[3], ... e[e-1].
Index from 0 to d^e-1 = e[0] + e[1]*d + e[2]*d*d + e[3]*d*d*d ...
There are 1+e iterIndexs.
By adding an e iterIndex, 1+e iterIndexs becomes 1+1 iterIndexs, and those are: d^e and d, plus the e iterIndex you just added.
Then the iterIndexs would be: d, e, d^e.
To add an i iterIndex, you can give a constant or loop over all possible constants from 0 to e-1. If loop, it increases the iterSize from d^e to e*(d^e), and if you wanted an iteration counter, it could go from 0 to e*(d^e)-1.
Therefore d^e changing to iteration size e*(d^e) and getting iterIndexs [e, d, d^e, e*(d^e)] is not an exception.

The power function requires the second parameter (in x^y its y) to be viewed as an array of iterIndex (each ranging 0 to first parameter size - 1). x^y having an iterOption with iterSize y*(x^y) is not an exception to a rule. It is looping over y as an array of iterIndex.

If using 3^5 and 4^5 together, there are 2 iterIndex arrays each size 5. One has int from 0 to 2 and the other has ints from 0 to 3.

Can the 2 iterIndex arrays (size 5 and size 3) of 3^5 and 5^3 be used together differently than if they were independent?

Can the 2 iterIndex arrays (both size 6) of 6^6 and the opposite 6^6 be used together differently than if they were independent.
x^y and y^x, where x and y are both size 6.

Does that change if x=y? Thats similar to factorial, but allows duplicates and therefore excluding some indexs. Again:
***********This factorial stuff is complex and should be added after POWER and MULTIPLY are added and the first version of Audivolv is working with mouse and speakers.***********

===================================================================================

IterOption for d^e:
IterSizes: d^e.
IterIndex quantity: 1+e
IterIndexs: d^e, e[0], e[1], e[2], e[3], ... e[e-1].
How to define that each e[?] is an index for d?


</nodeExecutor>






